#pragma once
#include <sys/socket.h>
#include <sys/types.h>

#include <iostream>
#include <unistd.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <string>

#include <cstring>

#include"log_pro.hpp"

using std::cin;
using std::cout;
using std::endl;

static const int backlog = 10; // 可修改全连接队列长度

class Socket
{
private:
    int _sockFd = -1;

public:
    int getSock()
    {
        return _sockFd;
    }

    void init()
    {
        _sockFd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockFd == -1)
        {
            lg(FATAL,"socket init fail!");
            exit(1);
        }
        int opt = 1;
        setsockopt(_sockFd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); // 设置让服务器可以快速重启
    }
    void Bind(uint16_t port)
    {
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(port);
        server.sin_addr.s_addr = htonl(INADDR_ANY);
        // server.sin_addr.s_addr=inet_addr("0.0.0.0");
        if (-1 == bind(_sockFd, (struct sockaddr *)&server, sizeof(server)))
        {
            lg(FATAL,"bind socket fail!");
            exit(2);
        }
    }
    void Listen()
    {
        if (-1 == listen(_sockFd, backlog))
        {
            lg(FATAL,"listen fail!");
            exit(3);
        }
    }

    int Accept(std::string &ip, uint16_t& port)
    {
        struct sockaddr_in remote;
        socklen_t len=sizeof(remote);
        int fd = accept(_sockFd, (struct sockaddr *)&remote, &len);
        if(fd==-1)
        {
            lg(WARNING,"accept fail!");
        }
        port=ntohs(remote.sin_port);
        char ipBuffer[32];
        inet_ntop(AF_INET,&remote.sin_addr,ipBuffer,sizeof(ipBuffer));
        ip=ipBuffer;
        return fd;
    }

};